package cn.blnp.net.flowable.boot.localize.flow.resurgence;

import cn.blnp.net.flowable.boot.service.RestartProcessInstanceService;
import cn.blnp.net.flowable.boot.service.TaskRecallService;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <h3>流程复活演示案例</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/6/19 17:53
 */
@Slf4j
@SpringBootTest
public class ProcessRevivalTest {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private IdentityService identityService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private TaskRecallService taskRecallService;
    @Resource
    private RestartProcessInstanceService restartProcessInstanceService;

    SimplePropertyPreFilter taskFilter = new SimplePropertyPreFilter(Task.class,
            "id", "name", "executionId", "taskDefinitionKey");
    SimplePropertyPreFilter executionFilter = new SimplePropertyPreFilter(Execution.class,
            "id", "parentId", "processInstanceId", "activityId", "isScope");

    /**
     *  <h1>流程复活案例演示</h1>
     *  <ul>
     *      <li><b>流程定义文件：</b>{@link flow/restartProcessInstanceProcess.bpmn20.xml}</li>
     *      <li>
     *          <b>流程预览图：</b></br>
     *          <img src="https://cdn4.winhlb.com/2025/06/19/6853dee023368.png" >
     *      </li>
     *  </ul>
     **/
    @Test
    public void test() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("flow/restartProcessInstanceProcess.bpmn20.xml")
                .name("流程复活演示案例")
                .deploy();
        log.info("部署ID：{}", deploy.getId());
        //流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        log.info("流程定义ID：{}", processDefinition.getId());

        //初始化流程变量
        Map<String, Object> variables = MapUtil.builder(new HashMap<String, Object>())
                .put("applyUserId", "妲己")
                .put("applyNum", 100)
                .put("totalAmount", 9999.99)
                .build();

        //启动流程实例
        ProcessInstance procInst = runtimeService.startProcessInstanceById(processDefinition.getId(), variables);
        log.info("流程实例ID：{}", procInst.getId());

        log.info("== 开始自动办理当前流程任务！");
        //自动办理直到流程结束
        autoCompleteTasks(procInst.getId());

        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(procInst.getId())
                .singleResult();
        if (instance != null && instance.getEndTime() != null) {
            log.info("流程已结束！");
        }

        log.info("== 尝试复活流程实例！");
        restartProcessInstanceService.executeRestart(procInst.getId(), Arrays.asList("userTask2", "userTask3", "userTask4"));
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(procInst.getId()).list();
        log.info("复活后，当前任务为：{}", JSON.toJSONString(tasks, taskFilter));
        List<Execution> executions = runtimeService.createExecutionQuery()
                .processInstanceId(procInst.getId()).list();
        log.info("当前执行实例有：{}", JSON.toJSONString(executions, executionFilter));
        Map<String, Object> newVarMap = runtimeService.getVariables(procInst.getId());
        log.info("运行时流程变量有：{}", JSON.toJSONString(newVarMap));

        /**
         *  演示结果：
         **/
    }

    /**
     * <p><b>用途:自动办理流程任务<b></p>
     * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
     * @since 8:57 2025/6/20
     * @params [processInstanceId]
     * @param processInstanceId
     * @return void
    **/
    private void autoCompleteTasks(String processInstanceId) {
        boolean isProcessInstanceEnded = false;
        while (!isProcessInstanceEnded) {
            List<Task> tasks = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId).list();
            if (!CollectionUtils.isEmpty(tasks)) {
                for (Task task : tasks) {
                    taskService.complete(task.getId());
                }
            }
            HistoricProcessInstance historicProcessInstance = historyService
                    .createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId).singleResult();
            if (historicProcessInstance.getEndTime() != null) {
                isProcessInstanceEnded = true;
            }
        }
    }
}
